package com.icbc.common.fileupload;


import com.icbc.cte.logging.Log;
import com.icbc.cte.logging.LogFactory;
import com.icbc.ctp.channel.IChannelRequest;
import com.icbc.ctp.channel.IChannelResponse;
import com.icbc.ctp.channel.IViewer;
import com.icbc.ctp.channel.annotations.ViewerParam;
import com.icbc.ctp.channel.http.HttpChannelRequest;
import com.icbc.ctp.channel.http.HttpChannelResponse;
import com.icbc.ctp.core.IChannelContext;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FileDownloadViewer
  implements IViewer
{
  private static final Log ctpLog = LogFactory.getCtpLog(FileDownloadViewer.class);
  

  private String id = null;
  @ViewerParam(isVariable=false, defaultValue="utf-8")
  private String encoding = "utf-8";
  
  @ViewerParam(isVariable=false, defaultValue="application/octet-stream; charset=utf-8")
  private String respContentType = "application/octet-stream; charset=utf-8";
  
  @ViewerParam(isVariable=false, defaultValue="utf-8")
  private String respEncode = "utf-8";
  
  @ViewerParam(isVariable=false, defaultValue="false")
  private String delAfterDownload = "false";
  

  private String openType = "attachment";
  
  public void doPresentation(IChannelRequest channelRequest, IChannelResponse channelResponse) throws Exception
  {
    HttpServletRequest request = ((HttpChannelRequest)channelRequest).getHttpReqeust();
    

    IChannelContext context = channelRequest.getChannelContext();
    HttpServletResponse response = ((HttpChannelResponse)channelResponse).getHttpResponse();
    


    request.setCharacterEncoding(encoding);
    
    String fileName = (String)context.getValueAt("fileName");
    if ((fileName == null) || (fileName.equals(""))) {
      fileName = request.getParameter("fileName");
    }
    String showFileName = (String)context.getValueAt("showFileName");
    if ((showFileName == null) || (showFileName.equals(""))) {
      showFileName = request.getParameter("showFileName");
    }
    openType = ((String)context.getValueAt("openType"));
    if ((openType == null) || (openType.equals(""))) {
      openType = request.getParameter("openType");
    }
    
    if ((fileName == null) || (fileName.equals(""))) {
      ctpLog.error("->file4ctp:FileDownloadViewer", "Filedownload do not appoint the file name.");
      throw new Exception("file4ctp:FileDownloadViewer Filedownload do not appoint the file name.");
    }
    
    int fileLen = 0;
    
    File aFile = new File(fileName);
    if (!aFile.exists()) {
      ctpLog.error("->file4ctp:FileDownloadViewer", "The specificed file :" + fileName + "do not exist");
      throw new Exception("file4ctp:FileDownloadViewer file " + fileName + " not found");
    }
    if (aFile.isDirectory()) {
      ctpLog.error("->file4ctp:FileDownloadViewer", "The specificed file:" + fileName + "is folder");
      throw new Exception("file4ctp:FileDownloadViewer file " + fileName + " is  directory");
    }
    fileLen = (int)aFile.length();
    
    if ((showFileName == null) || (showFileName.trim().length() == 0)) {
      String fName = fileName.replace("\\", "/");
      
      int idx = fName.lastIndexOf("/");
      if (idx != -1) {
        fName = fName.substring(idx + 1);
      }
      
      showFileName = fName;
    }
    
    if ((openType == null) || (openType.trim().length() == 0)) {
      openType = "attachment";
    } else {
      openType = (openType.equals("inline") ? openType : "attachment");
    }
    
    response.setContentType(respContentType);
    
    String str = "";
    if (respEncode.toUpperCase().equals("GBK")) {
      str = new String(showFileName.getBytes("GBK"), "ISO8859_1");
    } else {
      //str = URLEncoder.encode(showFileName, respEncode); //foxfire upload file problem
      str =request.getHeader("user-agent").contains("MSIE")?("="+URLEncoder.encode(showFileName,"utf-8")):"*=utf-8''"+URLEncoder.encode(showFileName,"utf-8");
    }
    //response.setHeader("Content-disposition", openType + "; filename=" + str);//foxfire upload file problem
    response.setHeader("Content-disposition", openType + "; filename" + str);

    ServletOutputStream os = null;
    FileInputStream fin = null;
    try {
      byte[] buffer = new byte[1024];
      int len = 0;
      
      os = response.getOutputStream();
      if (os != null) {
        response.setContentLength(fileLen);
        fin = new FileInputStream(fileName);
        while (len < fileLen) {
          int remainedLen = fileLen - len;
          if (remainedLen > 1024) {
            remainedLen = 1024;
          }
          int readLen = fin.read(buffer, 0, remainedLen);
          os.write(buffer, 0, readLen);
          len += readLen;
        }
        os.flush();
      }
    }
    catch (Exception e)
    {
      throw e;
    } finally {
      if (fin != null) {
        fin.close();
      }
      try {
        if (!"false".equalsIgnoreCase(delAfterDownload)) {
          aFile.delete();
        }
      }
      catch (Exception e2) {}
      if (os != null) {
        os.close();
      }
    }
  }
  
  public String getId()
  {
    return id;
  }
  
  public void setId(String id) {
    this.id = id;
  }
  
  public String getEncoding() {
    return encoding;
  }
  
  public void setEncoding(String encoding) {
    this.encoding = encoding;
  }
  
  public String getRespContentType() {
    return respContentType;
  }
  
  public void setRespContentType(String respContentType) {
    this.respContentType = respContentType;
  }
  
  public String getRespEncode() {
    return respEncode;
  }
  
  public void setRespEncode(String respEncode) {
    this.respEncode = respEncode;
  }
  
  public String getDelAfterDownload() {
    return delAfterDownload;
  }
  
  public void setDelAfterDownload(String delAfterDownload) {
    this.delAfterDownload = delAfterDownload;
  }
}